
import mpd
from types import FunctionType

# Provide attribute-style access to dictionary members, like d.name
# instead of d['name']
class Attrs:
    def __init__(self, d):
        self.d = d

    def __getattr__(self, name):
        try:
            return self.d[name]
        except KeyError:
            # FIXME this is terrible
            if name == 'song':
                return '0'
            raise AttributeError


class ConnectionRetryError(Exception): pass

# python-mpd client seems to drop the connection after it's been idle, so this
# is a fiddly attempt to make it possible to reconnect and re-issue a command
# when one of the mpd client methods is called and fails
class Client:
    def __init__(self, host, port=6600):
        self.__host = host
        self.__port = port
        self.__client = mpd.MPDClient()
        self.__max_connection_retries = 5

    def __getattr__(self, name):
        try:
            if type(self.__client.__getattr__(name)) == FunctionType:
                def handler(*args):
                    for i in range(self.__max_connection_retries):
                        try:
                            return self.__client.__getattr__(name)(*args)
                        except mpd.ConnectionError:
                            try: self.__client.disconnect()
                            except mpd.ConnectionError: pass
                            self.__client.connect(self.__host, self.__port)
                    raise ConnectionRetryError
                return handler
            else:
                return self.__client.__getattr__(name)
        except AttributeError, r:
            try:
                return self.__client.__getattribute__(name)
            except AttributeError:
                raise AttributeError, r
